﻿using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EchoClient
{
    public class EchoClientHandler : SimpleChannelInboundHandler<IByteBuffer>
    {
        /*
         SimpleChannelInboundHandler 继承自 ChannelHandlerAdapter，前者更强大的地方是对于资源的自动释放
         Read0是DotNetty特有的对于Read方法的封装
         封装实现了：
         1. 返回的message的泛型实现
         2. 丢弃非该指定泛型的信息
         */
        protected async override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg)
        {
            if (msg != null)
            {
                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.FFFFFFF}Receive From Server:{ msg.ToString(Encoding.UTF8)}");
            }
            await ctx.WriteAsync(Unpooled.CopiedBuffer(msg));
        }

        public override void ChannelReadComplete(IChannelHandlerContext context)
        {
            context.Flush();
        }

        public async override void ChannelActive(IChannelHandlerContext context)
        {
            Console.WriteLine("发送Hello World");
            //直接将msg发送出去失败了?
            //因为引用计数器机制，IByteBuffer只能使用一次，而在使用Read0方法接收这个消息的时候，这个消息的引用计数就被归零了，这时候我们再次使用就会报出异常，所以这里需要将源消息再复制一份。
            //如果使用的Read方法则不会有这样的问题。原则上来说，不应该存储指向任何消息的引用供未来使用，因为这些引用都会自动失效（意思就是消息收到了处理完就丢掉，消息不应该被长久保存）
            await context.WriteAndFlushAsync(Unpooled.CopiedBuffer(Encoding.UTF8.GetBytes("Hello World!")));
        }

        public async override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Console.WriteLine(exception);
            await context.CloseAsync();
        }
    }
}
